package com.occamlab.te.parsers; import java.io.InputStream; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Source; import javax.xml.transform.Templates; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import com.occamlab.te.Test; import com.occamlab.te.util.DomUtils; import com.occamlab.te.util.URLConnectionUtils; public class XSLTransformationParser { private static final Logger LOGR = Logger .getLogger(XSLTransformationParser.class.getName()); DocumentBuilder db = null; TransformerFactory tf = null; Templates defaultTemplates = null; HashMap<String, String> defaultProperties = null; HashMap<String, String> defaultParams = null; Boolean defaultIgnoreErrors; Boolean defaultIgnoreWarnings; private Source getSource(String reftype, String ref) throws Exception { if (reftype.equals("url")) { URL url = new URL(ref); return new StreamSource(url.openStream()); } else if (reftype.equals("file")) { return new StreamSource(ref); } else if (reftype.equals("resource")) { ClassLoader cl = getClass().getClassLoader(); return new StreamSource(cl.getResourceAsStream(ref)); } return null; } private Templates parseInstruction(Element instruction, HashMap<String, String> properties, HashMap<String, String> params, Boolean ignoreErrors, Boolean ignoreWarnings) throws Exception { Templates templates = null; final String[] atts = { "url", "file", "resource" }; for (String att : atts) { String val = instruction.getAttribute(att); if (val.length() > 0) { templates = tf.newTemplates(getSource(att, val)); break; } } Element stylesheet = DomUtils.getElementByTagNameNS(instruction, Test.XSL_NS, "stylesheet"); if (stylesheet == null) { stylesheet = DomUtils.getElementByTagNameNS(instruction, Test.XSL_NS, "transform"); } if (stylesheet != null) { templates = tf.newTemplates(new DOMSource(stylesheet)); } List<Element> children = DomUtils.getChildElements(instruction); for (Element e : children) { if (e.getLocalName().equals("property") && e.getNamespaceURI().equals(Test.CTLP_NS)) { properties.put(e.getAttribute("name"), e.getTextContent()); } if (e.getLocalName().equals("with-param") && e.getNamespaceURI().equals(Test.CTLP_NS)) { params.put(e.getAttribute("name"), e.getTextContent()); } } String ignoreErrorsAtt = instruction.getAttribute("ignoreErrors"); if (ignoreErrorsAtt != null) { ignoreErrors = Boolean.parseBoolean(ignoreErrorsAtt); } String ignoreWarningsAtt = instruction.getAttribute("ignoreWarnings"); if (ignoreWarningsAtt != null) { ignoreWarnings = Boolean.parseBoolean(ignoreWarningsAtt); } return templates; } public XSLTransformationParser() throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); db = dbf.newDocumentBuilder(); tf = TransformerFactory.newInstance(); defaultProperties = new HashMap<String, String>(); defaultParams = new HashMap<String, String>(); defaultIgnoreErrors = new Boolean(false); defaultIgnoreWarnings = new Boolean(true); } public XSLTransformationParser(Node node) throws Exception { super(); defaultTemplates = parseInstruction(DomUtils.getElement(node), defaultProperties, defaultParams, defaultIgnoreErrors, defaultIgnoreWarnings); } public XSLTransformationParser(String reftype, String ref) throws Exception { super(); defaultTemplates = tf.newTemplates(getSource(reftype, ref)); } public Document parse(URLConnection uc, Element instruction, PrintWriter logger) throws Exception { HashMap<String, String> properties = new HashMap<String, String>(); properties.putAll(defaultProperties); HashMap<String, String> params = new HashMap<String, String>(); params.putAll(defaultParams); Boolean ignoreErrors = defaultIgnoreErrors; Boolean ignoreWarnings = defaultIgnoreWarnings; Templates templates = parseInstruction(instruction, properties, params, ignoreErrors, ignoreWarnings); Transformer t = null; if (templates != null) { t = templates.newTransformer(); } else if (defaultTemplates != null) { t = defaultTemplates.newTransformer(); } else { t = tf.newTransformer(); } for (Entry<String, String> prop : properties.entrySet()) { t.setOutputProperty(prop.getKey(), prop.getValue()); } for (Entry<String, String> param : params.entrySet()) { // System.out.println(param.getKey() + ": " + param.getValue()); t.setParameter(param.getKey(), param.getValue()); } XSLTransformationErrorHandler el = new XSLTransformationErrorHandler( logger, ignoreErrors, ignoreWarnings); t.setErrorListener(el); Document doc = db.newDocument(); InputStream is = null; try { if (LOGR.isLoggable(Level.FINER)) { String msg = String .format("Attempting to transform source from %s using instruction set:\n %s", uc.getURL(), DomUtils.serializeNode(instruction)); LOGR.finer(msg); } // may return error stream is = URLConnectionUtils.getInputStream(uc); t.transform(new StreamSource(is), new DOMResult(doc)); } catch (TransformerException e) { el.error(e); } finally { if (null != is) is.close(); } if (el.getErrorCount() > 0 && !ignoreErrors) { return null; } if (el.getWarningCount() > 0 && !ignoreWarnings) { return null; } return doc; } }